package models

import (
	"fmt"
	"github.com/prometheus/prometheus/model/relabel"
	"gopkg.in/yaml.v3"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"strconv"
)

// 采集任务 和机器的关系
// 1对多 机器只能属于1个采集任务
// 新建采集任务 就需要填入ip
// 主配置文件池
// job 对象 机器：ip+port
//
//	2 k8s 的服务发现：集群外部采集
type MonitorScrapeJob struct {
	Model        // 不用每次写ID 和 createAt了
	Name  string `json:"name" validate:"required,min=1,max=50" gorm:"uniqueIndex;type:varchar(100);comment:采集任务名称，支持使用通配符*进行模糊搜索" `

	// D:\nyy_work\go_path\src\github.com\prometheus\prometheus\config\config.go
	// 下面是global段
	UserID uint

	// 公共的
	Enable                   int    `json:"enable" gorm:"comment:是否被开启 1正常 2关闭"` //用户是否被冻结 1正常 2冻结
	ServiceDiscoveryType     string `json:"serviceDiscoveryType" gorm:"comment: k8s or tree-http"`
	MetricsPath              string `json:"metricsPath"`
	Scheme                   string `json:"scheme"`
	ScrapeInterval           int    `json:"scrapeInterval" gorm:"comment: 采集间隔"`
	ScrapeTimeout            int    `json:"scrapeTimeout" gorm:"comment: 采集超时时间"`
	PoolId                   uint   `json:"poolId"`
	RelabelConfigsYamlString string `json:"relabelConfigsYamlString" gorm:"type:text;comment: 是yaml的字符串，unmarshal塞入"`

	// 服务树http类型的
	RefreshInterval int `json:"refreshInterval" gorm:"comment: 刷新target间隔"`
	Port            int `json:"port" gorm:"comment: 用虚拟机类型的时候  服务树服务发现接口 需要传port"`

	// 因为gorm 只支持 stringArray 而不支持 intArr
	TreeNodeIds StringArray `json:"treeNodeIds" gorm:"comment: 如果使用了 服务树接口 ，那么绑定的 树id列表，进而获取ip列表"`

	// 下面是关于 k8s集群外部采集
	KubeconfigFilePath string `json:"kubeconfigFilePath" gorm:"comment: 连接apiserver 文件得自己放好"`
	TlsCaFilePath      string `json:"tlsCaFilePath" gorm:"comment: tls ca证书 文件得自己放好"`
	TlsCaContent       string `json:"tlsCaContent" gorm:"comment: tls ca证书内容"`
	BearerToken        string `json:"bearerToken" gorm:"comment: 鉴权的文件内容"`
	BearerTokenFile    string `json:"bearerTokenFile" gorm:"comment: 鉴权的文件"`
	KubernetesSdRole   string `json:"kubernetesSdRole"`
	// relabel_configs  string 可以设计成 yaml string yamlUnmarsh  ，在k8s中 根据经验自己添加一些
	// 关于服务发现 支持有限的几种 k8s http

	TreeNodeIdInts []int  `json:"treeNodeIdInts" gorm:"-"`
	Key            string `json:"key" gorm:"-"`      //给前端表格
	PoolName       string `json:"poolName" gorm:"-"` //给前端表格
	CreateUserName string `json:"createUserName" gorm:"-"`
}

func (obj *MonitorScrapeJob) Create() error {
	return Db.Create(obj).Error

}
func (obj *MonitorScrapeJob) DeleteOne() error {

	return Db.Select(clause.Associations).Unscoped().Delete(obj).Error

}

func (obj *MonitorScrapeJob) CreateOne() error {
	return Db.Create(obj).Error

}

func (obj *MonitorScrapeJob) UpdateOne() error {
	return Db.Debug().Where("id = ?", obj.ID).Updates(obj).Error

}

func (obj *MonitorScrapeJob) IdsConvert() {
	// 把 int ids 转化为 string ids
	strIds := []string{}
	for _, id := range obj.TreeNodeIdInts {
		strIds = append(strIds, fmt.Sprintf("%d", id))
	}
	obj.TreeNodeIds = strIds
}

func (obj *MonitorScrapeJob) ValidateRelabelConfigsYamlString() error {
	var relabelConfigsObj []*relabel.Config
	return yaml.Unmarshal([]byte(obj.RelabelConfigsYamlString), &relabelConfigsObj)

}

func (obj *MonitorScrapeJob) FillFrontAllData() {
	dbUser, _ := GetUserById(int(obj.UserID))
	if dbUser != nil {
		obj.CreateUserName = dbUser.Username
	}

	dbPoll, _ := GetMonitorScrapePoolById(int(obj.PoolId))
	if dbPoll != nil {
		obj.PoolName = dbPoll.Name
	}

	obj.Key = fmt.Sprintf("%d", obj.ID)
	ids := []int{}
	for _, id := range obj.TreeNodeIds {
		idInt, _ := strconv.Atoi(id)
		ids = append(ids, idInt)
	}
	obj.TreeNodeIdInts = ids

}
func GetMonitorScrapeJobAll() (objs []*MonitorScrapeJob, err error) {
	err = Db.Find(&objs).Error
	return
}

func GetMonitorScrapeJobCount() int {
	var count int64
	Db.Table("form_designs").Count(&count)
	return int(count)
}

func GetMonitorScrapeJobByLevel(level int) (objs []*MonitorScrapeJob, err error) {
	err = Db.Where("level = ?", level).Preload("OpsAdmins").Find(&objs).Error
	return
}

// select * from ecs where
func GetMonitorScrapeJobByIdsWithLimitOffset(ids []int, limit, offset int) (objs []*MonitorScrapeJob, err error) {
	err = Db.Limit(limit).Offset(offset).Find(&objs, ids).Error
	return
}

// 查询这个节点池管理的采集Job
func GetMonitorScrapeJobByPoolId(poolId uint) (objs []*MonitorScrapeJob, err error) {

	err = Db.Where("enable=1 and pool_id = ?", poolId).Find(&objs).Error
	return

}

func GetMonitorScrapeJobById(id int) (*MonitorScrapeJob, error) {

	var dbObj MonitorScrapeJob
	err := Db.Where("id = ?", id).First(&dbObj).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, fmt.Errorf("MonitorScrapeJob不存在")
		}
		return nil, fmt.Errorf("数据库错误:%w", err)
	}
	return &dbObj, nil

}
